#include <stdio.h>
#include <windows.h>

int stop;
HANDLE hth;
int com_port = 1;
HANDLE hmutex;

DWORD WINAPI ThreadProc(LPVOID lpParameter);
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	hmutex = CreateMutex(NULL, FALSE, "Global\\mutex_scanner_input_v1");
	if(!hmutex || GetLastError() == ERROR_ALREADY_EXISTS) return 0;

	//AllocConsole();
	//freopen("CONOUT$", "w", stdout);
	freopen("c:\\bcs.log", "w", stdout);

	setbuf(stdout, NULL);
	printf("Barcode Scanner Start...\n");
	printf("CMD: %s\n", lpCmdLine);

	const char *i = strstr(lpCmdLine, "/com");
	if(i) com_port = atoi(i + 4);

	WNDCLASS wc;
	memset(&wc, 0, sizeof(wc));
    wc.style = CS_HREDRAW | CS_VREDRAW; 
    wc.lpfnWndProc = (WNDPROC) MainWndProc; 
    wc.hInstance = hInstance; 
    wc.lpszMenuName =  "MainMenu"; 
    wc.lpszClassName = "MainWindowClass";
	if (!RegisterClass(&wc)) return FALSE; 

	HWND hwnd = CreateWindow("MainWindowClass", "", WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInstance, NULL);
	ShowWindow(hwnd, SW_HIDE);
	UpdateWindow(hwnd);
	printf("HWND: %08X\n", hwnd);

	stop = 0;
	hth = CreateThread(NULL, 0, ThreadProc, 0, 0, NULL);
	
	MSG msg;
	while( GetMessage(&msg, NULL, 0, 0) > 0 )
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg); 
	}

	return 0;
}

LRESULT WINAPI MainWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	switch(Msg)
	{
		case WM_QUERYENDSESSION:
		{
			printf("WM_QUERYENDSESSION\n");
			return 1;
			break;
		}
		case WM_ENDSESSION:
		{
			printf("WM_ENDSESSION\n");
			stop = 1;
			WaitForSingleObject(hth, INFINITE);
			CloseHandle(hth);
			hth = NULL;
			break;
		}

		default:
			return DefWindowProc(hWnd, Msg, wParam, lParam);
	}

	return 0;
}


DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
	HANDLE hevent = CreateEvent(NULL, TRUE, TRUE, NULL);
	OVERLAPPED ov;
	char buf[1];
	DWORD nr;
	int no_err;
	INPUT ip[2];
	char fnz[64];

	memset(&ip, 0, sizeof(ip));
	sprintf(fnz, "\\\\.\\COM%d", com_port);

	printf("Start Input Thread..\n");
	while(!stop) {
		Sleep(500);

		HANDLE fh = CreateFile(fnz, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
		if(fh == INVALID_HANDLE_VALUE) continue;
		printf("Open ComPort[%d] - %08X\n", com_port, fh);

		while(!stop) {
			memset(&ov, 0, sizeof(ov));
			ov.hEvent = hevent;

			if(!ReadFile(fh, buf, sizeof(buf), &nr, &ov) ) {
				no_err = 0;
				if( GetLastError() != ERROR_IO_PENDING ) break;

				while(!stop) {
					WaitForSingleObject(hevent, 500);
					if( (no_err=GetOverlappedResult(fh, &ov, &nr, FALSE)) || GetLastError() != ERROR_IO_INCOMPLETE ) break;
				}

			} else
				no_err = 1;

			if(!no_err) break;

			if(buf[0] >= 0x30 && buf[0] <= 0x39 || buf[0] == '\r' || buf[0] == '\n') {
				ip[0].type = INPUT_KEYBOARD;
				ip[0].ki.wVk = buf[0];
				ip[0].ki.dwFlags = 0;
				ip[1].type = INPUT_KEYBOARD;
				ip[1].ki.wVk = buf[0];
				ip[1].ki.dwFlags = KEYEVENTF_KEYUP;
				SendInput(2, ip, sizeof(ip[0]));
			}

		}

		CloseHandle(fh);
	}

	CloseHandle(hevent);

	return 0;
}
